package crypt

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"io"
)

// CfbCrypt ...
type CfbCrypt struct {
	key string
}

// SetCryptKey ...
func (c *CfbCrypt) SetCryptKey(key string) error {
	c.key = key
	return nil
}

// ExistCryptKey ...
func (c *CfbCrypt) ExistCryptKey() bool {
	if c.key != "" {
		return true
	}
	return false
}


// Encrypt 加密
func (c *CfbCrypt) Encrypt(data []byte) (string,error) {
	if !c.ExistCryptKey() {
		return "", CryptKeynotFound
	}
	block, err := aes.NewCipher([]byte(c.key))
	if err != nil {
		return "", err
	}
	encrypted := make([]byte, aes.BlockSize+len(data))
	iv := encrypted[:aes.BlockSize]
	if _, err = io.ReadFull(rand.Reader, iv); err != nil {
		return "", err
	}
	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(encrypted[aes.BlockSize:], data)
	return string(encrypted),nil
}

// Decrypt 解密
func (c *CfbCrypt) Decrypt(data string) (interface{},error) {
	if !c.ExistCryptKey() {
		return nil, CryptKeynotFound
	}
	encrypted := []byte(data)
	block, _ := aes.NewCipher([]byte(c.key))
	if len(encrypted) < aes.BlockSize {
		return nil, CfbTooShortFail
	}
	iv := encrypted[:aes.BlockSize]
	encrypted = encrypted[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(encrypted, encrypted)
	return encrypted,nil
}
